package avicit.bdp.dgs.qa.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.datasource.DataSourceFactory;
import avicit.bdp.common.service.dto.DataSourceDTO;
import avicit.bdp.common.utils.database.DBUtils;
import avicit.bdp.common.utils.database.JdbcUtils;
import avicit.bdp.dgs.qa.dao.QaDataSourceDAO;
import avicit.bdp.dgs.qa.dto.FtdpFileDTO;
import avicit.bdp.dgs.qa.dto.QaDataSourceDTO;
import avicit.bdp.dgs.qa.utils.enums.MeasureType;
import avicit.platform6.api.system.ConvertColumnClient;
import avicit.platform6.api.system.impl.SystemConstant;
import avicit.platform6.commons.utils.BusinessUtil;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.commons.utils.PojoUtil;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;

/**
 * @金航数码科技有限责任公司
 * @作者：developer
 * @邮箱：developer@avic-digital.com
 * @创建时间： 2023-03-31
 * @类说明：RuleDataSourceService
 * @修改记录：
 * @注意事项：
 * @主要功能：质量规则数据源配置Service
 */
@Service
public class QaDataSourceService extends BaseService<QaDataSourceDAO, QaDataSourceDTO> {
    private static final Logger logger = LoggerFactory.getLogger(QaDataSourceService.class);

    @Autowired
    private avicit.bdp.common.service.service.DataSourceService dataSourceService;

    @Autowired
    private ConvertColumnClient convertColumnClient;

    /**
     * 根据业务ID获取数据源列表
     *
     * @param businessId
     * @return
     */
    public List<QaDataSourceDTO> getDsList(String businessId) {
        if (StringUtils.isEmpty(businessId)) {
            logger.error("查询数据源信息失败，业务ID为空.");
            return new ArrayList<>();
        }

        List<QaDataSourceDTO> dsList = this.mapper.getDsListByCond(businessId);
        valueConvert(dsList);

        return dsList;
    }

    /**
     * 批量插入
     *
     * @param dsList
     * @param businessId
     */
    public void batchInsertDs(String businessId, List<QaDataSourceDTO> dsList) {
        if (CollectionUtils.isEmpty(dsList)) {
            return;
        }

        List<QaDataSourceDTO> finalDsList = Lists.newArrayList();
        for (QaDataSourceDTO dto : dsList) {
            if (dto == null) {
                continue;
            }
            if (!checkAddValid(dto)) {
                continue;
            }

            if (isStructDataMeasure(dto.getMeasureType())) {
                avicit.bdp.common.service.dto.DataSourceDTO dataSourceDTO = this.dataSourceService.selectByPrimaryKey(dto.getDatasourceId());
                if (dataSourceDTO == null) {
                    continue;
                }
                dto.setDatasourceType(dataSourceDTO.getDatasourceType());
                dto.setDatasourceName(dataSourceDTO.getDatasourceName());
            }

            dto.setId(ComUtil.getId());
            dto.setBusinessId(businessId);
            PojoUtil.setSysProperties(dto, PlatformConstant.OpType.insert);

            finalDsList.add(dto);
        }

        if (CollectionUtils.isNotEmpty(finalDsList)) {
            this.mapper.batchInsertDs(finalDsList);
        }
    }

    /**
     * 批量更新
     *
     * @param businessId
     * @param dsList
     */
    public void batchUpdateDs(String businessId, List<QaDataSourceDTO> dsList) {
        this.mapper.deleteDsByCond(businessId, null);

        this.mapper.batchInsertDs(dsList);
    }

    /**
     * 删除/批量删除规则数据源
     *
     * @param businessId 业务ID
     * @param idList     数据源ID列表
     * @return
     */
    public int deleteDsByCond(String businessId, List<String> idList) {
        return this.mapper.deleteDsByCond(businessId, idList);
    }

    /**
     * 查询指定时间段内校验表和校验字段信息
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public List<QaDataSourceDTO> getCheckTableList(String startTime, String endTime) {
        return this.mapper.getCheckTableList(startTime, endTime);
    }

    /**
     * SQL语法校验
     *
     * @param datasourceId
     * @param sql
     * @return
     */
    public boolean checkGrammar(String datasourceId, String sql) {
        if (StringUtils.isEmpty(datasourceId)) {
            logger.error("数据源ID不存在.");
            return false;
        }

        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        DataSourceDTO dataSourceDTO = this.dataSourceService.queryDataSourceById(datasourceId);
        try {
            conn = DBUtils.buildConnectionFromPool(DataSourceFactory.getDatasource(dataSourceDTO));
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
        } catch (Exception e) {
            logger.error("SQL:{}校验失败", sql, e);
            throw new BusinessException(String.format("SQL语法校验失败，SQL如下：%s，失败原因：%s", sql, e.getMessage()));
        } finally {
            JdbcUtils.close(rs);
            JdbcUtils.close(stmt);
            JdbcUtils.close(conn);
        }

        logger.info("sql:{}校验通过", sql);

        return true;
    }

    /**
     * 根据试飞分类ID获取文件列表
     *
     * @param offsiteDataId
     * @param fileIdList
     * @return
     */
    public List<FtdpFileDTO> getFileList(String offsiteDataId, List<String> fileIdList) {
        return this.mapper.getFileList(offsiteDataId, fileIdList);
    }

    /**
     * 获取数据源类型
     *
     * @param datasourceId
     * @return
     */
    public String getDbType(String datasourceId) {
        if (StringUtils.isEmpty(datasourceId)) {
            logger.warn("数据源ID为null，获取数据源类型失败。");
            return null;
        }

        DataSourceDTO dataSourceDTO = this.dataSourceService.queryDataSourceById(datasourceId);
        if (dataSourceDTO != null) {
            return dataSourceDTO.getDatasourceType();
        }

        return null;
    }

    /**
     * 根据作业ID获取数据源类型
     *
     * @param jobId
     * @return
     */
    public String getDbTypeByJobId(String jobId) {
        if (StringUtils.isEmpty(jobId)) {
            return null;
        }

        return this.mapper.getDbTypeByJobId(jobId);
    }

    /**
     * 合法性检查
     *
     * @param dto
     * @return
     */
    private boolean checkAddValid(QaDataSourceDTO dto) {
        if (dto == null) {
            return false;
        }

        if (isStructDataMeasure(dto.getMeasureType())) {
            if (StringUtils.isBlank(dto.getDatasourceId())) {
                return false;
            }
            if (StringUtils.isBlank(dto.getDbName())) {
                return false;
            }
            if (StringUtils.isBlank(dto.getTableName())) {
                return false;
            }
        }

        return true;
    }

    /**
     * 通过平台API将字段值转换为名称，包括通用选择组件、通用代码
     *
     * @param dtoList
     */
    private void valueConvert(List<QaDataSourceDTO> dtoList) {
        if (CollectionUtils.isEmpty(dtoList)) {
            return;
        }

        // 设置创建者名称
        Map<String, Set<String>> convertFormData = new HashMap<>();
        for (QaDataSourceDTO dto : dtoList) {
            BusinessUtil.createConvertSet(convertFormData, SystemConstant.USER, dto.getCreatedBy());
        }
        if (convertFormData.size() > 0) {
            //获取请求结果
            Map<String, Map<String, String>> convertResultData = convertColumnClient.replace(convertFormData);
            //循环设置Alias或Name的值
            for (QaDataSourceDTO dto : dtoList) {
                dto.setCreatedBy(BusinessUtil.convertFormat(convertResultData, SystemConstant.USER, dto.getCreatedBy()));
            }
        }
    }

    /**
     * 是否为结构化数据校验
     *
     * @param type
     * @return
     */
    private boolean isStructDataMeasure(Integer type) {
        if (type != null) {
            return type == MeasureType.SINGLE_SOURCE.getCode() || type == MeasureType.MULTI_SOURCE.getCode();
        }

        return false;
    }
}
